{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "“Word2Vec-Torch(Softmax).ipynb”的副本",
      "provenance": [],
      "collapsed_sections": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "code",
      "metadata": {
        "id": "bqUKpxrLsDdp",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "'''\n",
        "  code by Tae Hwan Jung(Jeff Jung) @graykode, modify by wmathor\n",
        "'''\n",
        "import torch\n",
        "import numpy as np\n",
        "import torch.nn as nn\n",
        "import torch.optim as optimizer\n",
        "import torch.utils.data as Data\n",
        "\n",
        "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
        "dtype = torch.FloatTensor"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "OteNgpGiuIAL",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "sentences = [\"jack like dog\", \"jack like cat\", \"jack like animal\",\n",
        "  \"dog cat animal\", \"banana apple cat dog like\", \"dog fish milk like\",\n",
        "  \"dog cat animal like\", \"jack like apple\", \"apple like\", \"jack like banana\",\n",
        "  \"apple banana jack movie book music like\", \"cat dog hate\", \"cat dog like\"]\n",
        "sentence_list = \" \".join(sentences).split() # ['jack', 'like', 'dog']\n",
        "vocab = list(set(sentence_list))\n",
        "word2idx = {w:i for i, w in enumerate(vocab)}\n",
        "vocab_size = len(vocab)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "qP95fgZduiQ5",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# model parameters\n",
        "C = 2 # window size\n",
        "batch_size = 8\n",
        "m = 2 # word embedding dim"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "fpvih6WlvFib",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "skip_grams = []\n",
        "for idx in range(C, len(sentence_list) - C):\n",
        "  center = word2idx[sentence_list[idx]]\n",
        "  context_idx = list(range(idx - C, idx)) + list(range(idx + 1, idx + C + 1))\n",
        "  context = [word2idx[sentence_list[i]] for i in context_idx]\n",
        "\n",
        "  for w in context:\n",
        "    skip_grams.append([center, w])"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "fSG4Hox3wv0b",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def make_data(skip_grams):\n",
        "  input_data = []\n",
        "  output_data = []\n",
        "  for a, b in skip_grams:\n",
        "    input_data.append(np.eye(vocab_size)[a])\n",
        "    output_data.append(b)\n",
        "  return input_data, output_data"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "SNGvrTT2xmyE",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "input_data, output_data = make_data(skip_grams)\n",
        "input_data, output_data = torch.Tensor(input_data), torch.LongTensor(output_data)\n",
        "dataset = Data.TensorDataset(input_data, output_data)\n",
        "loader = Data.DataLoader(dataset, batch_size, True)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "W6YsUmxzx3SZ",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "class Word2Vec(nn.Module):\n",
        "  def __init__(self):\n",
        "    super(Word2Vec, self).__init__()\n",
        "    self.W = nn.Parameter(torch.randn(vocab_size, m).type(dtype))\n",
        "    self.V = nn.Parameter(torch.randn(m, vocab_size).type(dtype))\n",
        "\n",
        "  def forward(self, X):\n",
        "    # X : [batch_size, vocab_size]\n",
        "    hidden = torch.mm(X, self.W) # [batch_size, m]\n",
        "    output = torch.mm(hidden, self.V) # [batch_size, vocab_size]\n",
        "    return output"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "qTrVrbNsy0bN",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "model = Word2Vec().to(device)\n",
        "loss_fn = nn.CrossEntropyLoss().to(device)\n",
        "optim = optimizer.Adam(model.parameters(), lr=1e-3)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "zDcjLp7Ty2Qs",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 722
        },
        "outputId": "bfda288b-08e2-42fc-9753-19657c7d097b"
      },
      "source": [
        "for epoch in range(2000):\n",
        "  for i, (batch_x, batch_y) in enumerate(loader):\n",
        "    batch_x = batch_x.to(device)\n",
        "    batch_y = batch_y.to(device)\n",
        "    pred = model(batch_x)\n",
        "    loss = loss_fn(pred, batch_y)\n",
        "\n",
        "    if (epoch + 1) % 1000 == 0:\n",
        "      print(epoch + 1, i, loss.item())\n",
        "    \n",
        "    optim.zero_grad()\n",
        "    loss.backward()\n",
        "    optim.step()"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "1000 0 2.0227136611938477\n",
            "1000 1 2.3798117637634277\n",
            "1000 2 2.391190528869629\n",
            "1000 3 2.285754680633545\n",
            "1000 4 1.9063193798065186\n",
            "1000 5 1.9651578664779663\n",
            "1000 6 1.8772828578948975\n",
            "1000 7 1.8816274404525757\n",
            "1000 8 2.006587028503418\n",
            "1000 9 2.313750982284546\n",
            "1000 10 1.9250341653823853\n",
            "1000 11 2.076404094696045\n",
            "1000 12 1.854898452758789\n",
            "1000 13 2.043060779571533\n",
            "1000 14 2.341153621673584\n",
            "1000 15 2.0698914527893066\n",
            "1000 16 1.57113778591156\n",
            "1000 17 2.1810097694396973\n",
            "1000 18 2.5944101810455322\n",
            "1000 19 2.2469565868377686\n",
            "1000 20 1.7212722301483154\n",
            "2000 0 1.816986083984375\n",
            "2000 1 2.1669414043426514\n",
            "2000 2 1.9809743165969849\n",
            "2000 3 2.0651090145111084\n",
            "2000 4 1.9306294918060303\n",
            "2000 5 1.8891253471374512\n",
            "2000 6 1.9777374267578125\n",
            "2000 7 2.491191864013672\n",
            "2000 8 2.0507924556732178\n",
            "2000 9 1.9459185600280762\n",
            "2000 10 1.6109706163406372\n",
            "2000 11 1.9266815185546875\n",
            "2000 12 2.2067410945892334\n",
            "2000 13 1.9121506214141846\n",
            "2000 14 2.201719045639038\n",
            "2000 15 2.2587637901306152\n",
            "2000 16 1.8647295236587524\n",
            "2000 17 2.351783275604248\n",
            "2000 18 2.361424207687378\n",
            "2000 19 2.099379301071167\n",
            "2000 20 2.117107391357422\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "9vT14L_izbWC",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 267
        },
        "outputId": "fdb89ebf-dabe-4516-caa9-976e0ec4ac4c"
      },
      "source": [
        "import matplotlib.pyplot as plt\n",
        "for i, label in enumerate(vocab):\n",
        "  W, WT = model.parameters()\n",
        "  x,y = float(W[i][0]), float(W[i][1])\n",
        "  plt.scatter(x, y)\n",
        "  plt.annotate(label, xy=(x, y), xytext=(5, 2), textcoords='offset points', ha='right', va='bottom')\n",
        "plt.show()"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXIAAAD6CAYAAAC8sMwIAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAAgAElEQVR4nO3de1xXVb7/8dcHRPGSYqmJ6YR2vAWIKCZqXn7SlI2p3cyabnaxcaw5His7NTYNY9Z0Tpw6ahezLLPs6Jh5q8YmTR/amCUY3gqvUeQtL4GAoCDr9wfCiKKJfOHr/vJ+Ph484rvYe+3PJh9vt2uvvbY55xAREe8K8ncBIiJSOQpyERGPU5CLiHicglxExOMU5CIiHqcgFxHxOM8FuZmtOod9ppvZzVVRj4iIv5k/5pE3adLERUREVNvx0tPTadSoEY0bN662Y4qI+FpKSsp+51zTk9tr+aOYiIgIkpOTz2nfBg0asGfPHoYMGcLPP/9MQUEBEyZMYMiQIQDMmDGDpKQkzIxOnTrxzjvvMHz4cK677jpuvvlm/vSnP5GRkcG0adMIDg725WmJiFQpM/u+vHa/BHllhYaGMm/ePBo2bMj+/fuJj49n8ODBfPPNN0yYMIFVq1bRpEkTDh48WGa/sWPHkp2dzVtvvYWZ+al6ERHf8mSQO+f44x//yIoVKwgKCmLnzp3s3buXzz77jKFDh9KkSRMALrzwwtJ9nn76abp3787UqVP9VbaISJXwZJDPnDmTffv2kZKSQkhICBEREeTn559xn27dupGSksLBgwfLBLyIiNd5btYKQFZWFs2aNSMkJIRly5bx/ffFw0b9+/dnzpw5HDhwAKDM0MqAAQN4/PHHGThwINnZ2X6pW0SkKnjuitzMuP322xk0aBDR0dHExcXRoUMHACIjIxk3bhx9+/YlODiY2NhYpk+fXrrv0KFDyc7OZvDgwXz88cfUrVvXT2chIuI7fpl+GBcX585l1sqBAwfo0qVL6RX42Zi75yB/3bGbnUcKuKROCE+0Ceem5hpaERHvMbMU51zcye2euSLftWsX/fr149FHHz3rfebuOcijmzPIKyr+y+rHIwU8ujkDQGEuIgHDM0HeokULtmzZUqF9/rpjd2mIl8grcvx1x24FuYgEDE/e7DxbO48UVKhdRMSLAjrIL6kTUqF2EREvCuggf6JNOHWDyj7BWTfIeKJNuJ8qEhHxPc+MkZ+LknFwzVoRkUAW0EEOxWGu4BaRQBbQQysiIjWBglxExOMU5CIiHqcgFxHxOAW5iIjHeSLI77//fr755huf9zt9+nQeeughn/crIlKdPDH98I033vB3CSIi5y2fX5GbWYSZpZnZdDPbYmYzzewqM/unmW01syt27dpFUlJS6T5RUVGkp6eTm5vLwIEDiYmJISoqitmzZwPQr1+/0pc1L168mC5dutCoUSMaNmxIZGRk6evbGjRowJgxY4iMjCQhIYF9+/aV7j969Gg6d+5MVFQUX3311Sl179u3j5tuuolu3brRrVs3/vnPf/r6VyMiUiWqamjl34D/AToc//otcCXwKPDH0+20ePFiWrRowbp169i4cSMDBgwo8/N9+/YxYsQI5s6dy3fffUd6ejrJyclMmjSJAwcOkJubS1xcHJs2baJv37785S9/Kd338OHDpKam8sorr3DvvfeecuzRo0czZswY1qxZw9y5c7n//vt98XsQEalyVTW08p1zbgOAmW0CljrnnJltACJOt1N0dDSPPPII//mf/8l1111H7969y/x89erV9OnTh9atW5OYmMi8efMAyMjIYOvWrQQFBTFs2DAA7rjjDm688cbSfW+77TYA+vTpw6FDh8jMzCzT95IlS8qMwx86dIicnBwaNGhw7r8FEZFqUFVBfuSE74tO+FwE1DIzioqKSjcoeXFyu3btWLt2LR9//DFPPvkkCQkJPPXUU6d0vnz5cpYsWcIXX3xBvXr16NevX7kvXzazcr8v73NRURGrV68mNDS0QicqIuJvfpm1Urt2bdauXQvA2rVr+e6774DitwDVq1ePO+64g7Fjx5ZuUyI+Pp4VK1awZcsWGjduTH5+PmlpaaxevRooDuP3338fgPfee48rr7yydN+S8fbPP/+cRo0a0ahRozJ9X3311UyePLn0c2pqqo/PWkSkavhl1krjxo05ePAgkZGRdO/enXbt2gGwYcMGxo4dS1BQECEhIbz66qtl9mvatClTp07liSeeYMeOHbRq1Ypf//rXxMfHA1C/fn2++uorJkyYQLNmzUrDGyA0NJTY2FgKCgp48803T6lp0qRJPPjgg3Tq1InCwkL69OnDlClTqvC3ICLiG555+fK3K5exctYMsg/s54KLmtD71rvo2Pv/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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "D_5Cauheztue",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    }
  ]
}